﻿@using Microsoft.FluentUI.AspNetCore.Components
@using eShopSupport.ServiceDefaults.Clients.Backend
@inject StaffBackendClient Backend
<EditForm EditContext="@editContext" OnValidSubmit="@SaveChangesAsync">
    <div class="details-grid @(editContext.IsModified() ? "modified": "")">
        <div>
            <FluentSelect TOption="TicketType" @bind-SelectedOption="@ticketType" Items="@allTicketTypes"
                Label="Case type" OptionText="@TicketTypeDisplayText" style="width: 100%; min-width: 12rem;"
                @bind-SelectedOption:after="@MarkTicketTypeModified" />
        </div>
        <div>
            <FluentTextField Label="Customer" style="width: 100%;" Value="@Ticket?.CustomerFullName" ReadOnly />
        </div>
        <div>
            <FluentSelect TOption="TicketStatus" @bind-SelectedOption="@ticketStatus" Items="@allTicketStatuses"
                Label="Status" OptionText="@TicketStatusDisplayText" style="width: 100%; min-width: 12rem;"
                @bind-SelectedOption:after="@MarkTicketStatusModified" />
        </div>
        <div class="product-picker">
            <FluentAutocomplete TOption="FindProductsResult" @bind-SelectedOptions="@ticketProduct" MaximumSelectedOptions="1"
                Label="Product" OptionText="@FindProductDisplayText" style="width: 100%; min-width: 12rem;"
                OnOptionsSearch="LookupProductAsync" @bind-SelectedOptions:after="@MarkTicketProductModified" />
        </div>
        <div class="actions">
            @if (!isSaving)
            {
                <FluentButton Type="@ButtonType.Submit" Appearance="Appearance.Accent" IconStart="@saveIcon" Style="margin-top: 0.5rem">
                    Save changes
                </FluentButton>
            }
            else
            {
                <FluentProgressRing />
            }
        </div>
    </div>
</EditForm>

@code {
    private readonly Icon saveIcon = new Icons.Regular.Size20.Save();
    EditContext editContext;

    readonly TicketType[] allTicketTypes = Enum.GetValues<TicketType>();
    readonly TicketStatus[] allTicketStatuses = Enum.GetValues<TicketStatus>();
    int loadedTicketId;
    TicketType ticketType;
    TicketStatus ticketStatus;
    IEnumerable<FindProductsResult>? ticketProduct;
    bool isSaving;

    [Parameter, EditorRequired]
    public TicketDetailsResult Ticket { get; set; } = default!;

    public TicketDetails() => editContext = new(this);

    protected override void OnParametersSet()
    {
        if (Ticket.TicketId != loadedTicketId)
        {
            loadedTicketId = Ticket.TicketId;
            ticketType = Ticket.TicketType;
            ticketStatus = Ticket.TicketStatus;
            ticketProduct = Ticket.ProductId.HasValue ? [new FindProductsResult(Ticket.ProductId.Value, Ticket.ProductBrand!, Ticket.ProductModel!)] : [];
        }
    }

    // Workaround for https://github.com/microsoft/fluentui-blazor/issues/2086
    private void MarkTicketTypeModified()
        => editContext.NotifyFieldChanged(FieldIdentifier.Create(() => ticketType));
    private void MarkTicketStatusModified()
        => editContext.NotifyFieldChanged(FieldIdentifier.Create(() => ticketStatus));
    private void MarkTicketProductModified()
        => editContext.NotifyFieldChanged(FieldIdentifier.Create(() => ticketProduct));

    async Task SaveChangesAsync()
    {
        isSaving = true;
        var productId = ticketProduct?.FirstOrDefault()?.ProductId;
        var saveTask = Backend.UpdateTicketDetailsAsync(Ticket.TicketId, productId, ticketType, ticketStatus);
        await Task.WhenAll(saveTask, Task.Delay(250));
        editContext.MarkAsUnmodified();

        // To avoid having the "save" button flash into existence before animating away,
        // keep the spinner on screen for a further 1s, giving time for the animation to complete
        StateHasChanged();
        await Task.Delay(1000);
        isSaving = false;
    }

    string TicketStatusDisplayText(TicketStatus status) => status switch
    {
        TicketStatus.Open => "⏳ Open",
        TicketStatus.Closed => "✅ Closed",
        _ => "Unknown"
    };

    string TicketTypeDisplayText(TicketType type) => type switch
    {
        TicketType.Question => "❔ Question",
        TicketType.Idea => "💭 Comment / idea",
        TicketType.Complaint => "👎 Complaint",
        TicketType.Returns => "📦 Returns",
        _ => "Unknown"
    };

    string FindProductDisplayText(FindProductsResult product) => $"{product.Model} ({product.Brand})";

    async Task LookupProductAsync(OptionsSearchEventArgs<FindProductsResult> args)
    {
        args.Items = !string.IsNullOrWhiteSpace(args.Text) ? await Backend.FindProductsAsync(args.Text) : [];
    }
}
